#include "mymutex.hpp"

#include<cstdio>
#include <iostream>
#include <string>
#include<cstring>
#include <vector>
#include <pthread.h>
#include <unistd.h>

using namespace std;

#define NUM 5 // 创建的线程数量

int tickets = 1000; // 总票数

class threadData
{
public:
    threadData(const string &threadname, pthread_mutex_t *mutex)
        : _threadname(threadname)
    {
        _lock = mutex;
    }

public:
    std::string _threadname; // 线程名称
    pthread_mutex_t *_lock;
};

string toHex(pthread_t tid)
{
    char buf[64];
    snprintf(buf, sizeof(buf), "0x%x", tid);

    return buf;
}

void *getTicket(void *args)
{
    // pthread_detach(pthread_self());
    threadData *td = static_cast<threadData *>(args);

    while (true)
    {
        {
            LockGuard lg(td->_lock);
            if (tickets > 0)
            {
                usleep(1000);
                printf("%s, tid=%s , Grab a ticket:%d, &tickets:%p\n", td->_threadname.c_str(), toHex(pthread_self()).c_str(), tickets, &tickets);
                tickets--;
            }
            else
            {
                break;
            }
        }

        usleep(20); // 模拟抢到票后不能立即抢票 防止饥饿问题
    }

    printf("%s quit...\n", td->_threadname.c_str());

    // delete td;
    return nullptr;
}

int main()
{
    vector<pthread_t> tids;
    vector<threadData *> del;
    pthread_mutex_t lock;
    pthread_mutex_init(&lock, nullptr);

    for (int i = 1; i <= NUM; i++)
    {
        pthread_t tid;
        threadData *td = new threadData("thread " + to_string(i), &lock);
        del.push_back(td);
        pthread_create(&tid, nullptr, getTicket, td);
        tids.push_back(tid);
    }

    sleep(1); // 确保tid成功组织

    for (int i = 0; i < tids.size(); i++)
    {
        pthread_join(tids[i], nullptr);
    }

    for (int i = 0; i < del.size(); i++)
    {
        delete del[i];
    }

    pthread_mutex_destroy(&lock);
    printf("main thread quit...\n");
    return 0;
}